package com.platform.hjt.base.log;

import java.lang.reflect.Method;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.platform.hjt.base.costant.SessionConstant;
import com.platform.hjt.sys.model.SysCompanyInfo;
import com.platform.hjt.sys.model.SysUserInfo;

/**
 * 基础日志记录类
 * @author 吴智超
 * 2016-09-27
 */
@Aspect
@Component
public class LogAspect implements ILogAspect{
	
	@Resource
	protected HttpServletRequest request;
	protected Logger log = LoggerFactory.getLogger(LogAspect.class);
	
	@Override
	@Pointcut("@annotation(com.platform.hjt.base.log.AopLog)")
	public void log() {}

	@Override
	@Before("log()")
	public void befortAction(JoinPoint joinPoint) {
		AopLog anno = getAnnotaction(joinPoint);
		if(checkType(anno, AopConstant.BEFORE)){
			handleLog(joinPoint, null, null);
		}
	}

	@Override
	@After("log()")
	public void afterAction(JoinPoint joinPoint) {
		AopLog anno = getAnnotaction(joinPoint);
		if(checkType(anno, AopConstant.AFTER)){
			handleLog(joinPoint, null, null);
		}
	}

	@Override
	@AfterReturning(pointcut = "log()", returning = "returnObj")
	public void after(JoinPoint joinPoint, Object returnObj) {
		AopLog anno = getAnnotaction(joinPoint);
		if(checkType(anno, AopConstant.AFTER_RETURN)){
			handleLog(joinPoint, null, returnObj);
		}
	}

	@Override
	@AfterThrowing(pointcut = "log()", throwing = "e")
	public void after(JoinPoint joinPoint, Exception e) {
		AopLog anno = getAnnotaction(joinPoint);
		if(checkType(anno, AopConstant.AFTER_TRHOW)){
			handleLog(joinPoint, e, null);
		}
	}

	@Override
	/**
	 * 环绕通知与前置通知冲突，这里不启用
	 * @Around("log()")
	 */
	public void aroundAction(JoinPoint joinPoint) {
		AopLog anno = getAnnotaction(joinPoint);
		if(checkType(anno, AopConstant.AROUND)){
			handleLog(joinPoint, null, null);
		}
	}
	
	/**
	 * 默认处理日志操作，按需要重写
	 */
	@Override
	public void handleLog(JoinPoint joinPoint, Exception e, Object returnObj) {
		System.out.println("=======123========");
		
		
		try {
	        String signature = joinPoint.getSignature().toString();
	        
	        System.out.println(signature);
	        
	        String methodName = signature.substring(signature.lastIndexOf(".") + 1, signature.indexOf("("));
	        String classType = joinPoint.getTarget().getClass().getName();
	        Class<?> clazz = Class.forName(classType);
	        Method[] methods = clazz.getDeclaredMethods();
	        
	        joinPoint.getArgs();
	        
	        /*String user = getLoginUser(request);
	        String group = getUserGroup(request);*/
	        
	        /*for (Method method : methods) {
	            if (method.isAnnotationPresent(AopLog.class) && method.getName().equals(methodName)) {
	            	AopLog anno = method.getAnnotation(AopLog.class);
	            	
	            	String outputParam = StringUtils.substringBetween(anno.outputs(), "{", "}");
	            	String inputParam = StringUtils.substringBetween(anno.inputs(), "{", "}");
	            	String inputValue = "";
	            	String outputValue = "";
	            	if(StringUtils.isNotBlank(outputParam)){
	            		if(outputParam.indexOf(",") > -1){
	            			String[] params = outputParam.split(",");
	            			for(String output : params){
	            				String tmp = request.getParameter(output);
	            				outputValue += output + ":" + tmp + "; ";
	            			}
	            		}
	            	}
	            	
	            	if(StringUtils.isNotBlank(inputParam)){
	            		if(inputParam.indexOf(",") > -1){
	            			String[] params = inputParam.split(",");
	            			for(String input : params){
	            				Object tmp = request.getAttribute(input);
	            				if(tmp != null){
	            					inputValue += "<" + tmp.getClass() + ">:" + input + ":" + tmp + "; ";
	            				}
	            			}
	            		}
	            	}
	            	
	                int type = anno.aopType();
	                String clazzName = clazz.getName();
	                log.info("{}：部门【{}】用户【{}】执行类【{}】方法【{}】，传入参数【{}】，接收到参数【{}】", new Object[]{AopEnum.getNameByCode(type), group, user, clazzName, methodName, outputValue, inputValue});
	                break;
	            }  
	        }  */
	        if(e != null){
	        	log.error("方法执行异常，异常堆栈：", e);  
	        }
		} catch (Exception exp) {  
	    	log.error("异常信息:{}", exp.getMessage());  
	        exp.printStackTrace();  
        } 
	}

	/**
	 * 获取注解
	 * @param joinPoint
	 * @return
	 */
	public AopLog getAnnotaction(JoinPoint joinPoint){
		Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        AopLog aopLog = null;
        if (method != null) {
        	aopLog = method.getAnnotation(AopLog.class);
        }
        return aopLog;
	}
	
	/**
	 * 检查annotation是否要进行此类别的日志操作
	 */
	public boolean checkType(AopLog aopLog, int type) {
		if(aopLog == null){
			return false;
		}else{
			if((type & aopLog.aopType()) == type){
				return true;
			}else{
				return false;
			}
		}
	}
	
	/**
	 * 获取当前登录用户
	 * @param request
	 * @return
	 */
	protected SysUserInfo getLoginUser(HttpServletRequest request){
		return (SysUserInfo) request.getSession().getAttribute(SessionConstant.SESSION_USER);
	}
	
	/**
	 * 获取当前登录公司
	 * @param request
	 * @return
	 */
	protected SysCompanyInfo getUserGroup(HttpServletRequest request) {
		return (SysCompanyInfo) request.getSession().getAttribute(SessionConstant.SESSION_COMPANY);
	}
	
}
